package com.fufan.mtsaas.modules.newtech.xjstech.service.impl;

import com.baomidou.mybatisplus.plugins.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fufan.mtsaas.constant.DefaultConstant;
import com.fufan.mtsaas.modules.base.log.service.TSysLogSvc;
import com.fufan.mtsaas.modules.base.sysmsg.dao.TSysMessageDao;
import com.fufan.mtsaas.modules.base.sysmsg.model.TSysMessage;
import com.fufan.mtsaas.modules.common.bo.response.RequestPojo;
import com.fufan.mtsaas.modules.common.bo.response.ResStatus;
import com.fufan.mtsaas.modules.common.bo.response.Result;
import com.fufan.mtsaas.modules.base.processinfo.dao.PProcessInfoDao;
import com.fufan.mtsaas.modules.base.processinfo.model.PProcessInfo;
import com.fufan.mtsaas.modules.sysmgr.tsysparam.bo.CirculationStatusBo;
import com.fufan.mtsaas.modules.sysmgr.tsysparam.bo.ProcessItemBo;
import com.fufan.mtsaas.modules.sysmgr.tsysparam.dao.TSysParamDao;
import com.fufan.mtsaas.modules.sysmgr.tsysparam.model.TSysParam;
import com.fufan.mtsaas.modules.newtech.xjstech.bo.request.XjsTechApproveRequest;
import com.fufan.mtsaas.modules.newtech.xjstech.bo.request.XjsTechSendSmaRequest;
import com.fufan.mtsaas.modules.newtech.xjstech.dao.XjsTechDao;
import com.fufan.mtsaas.modules.newtech.xjstech.model.XjsTech;
import com.fufan.mtsaas.modules.newtech.xjstechhis.dao.XjsTechHisDao;
import com.fufan.mtsaas.modules.newtech.xjsyearaudit.dao.XjsYearAuditDao;
import com.fufan.mtsaas.modules.sysmgr.sydept.dao.SYDeptDao;
import com.fufan.mtsaas.modules.sysmgr.syuser.dao.SYuserDao;
import com.fufan.mtsaas.modules.sysmgr.syuser.model.SYuser;
import com.fufan.mtsaas.tools.AESTool;
import com.fufan.mtsaas.util.SMSSender;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * 基础审批
 */
@Service("XjsTechSvcImplBase")
@Slf4j
@Primary
public class BaseApprove {
    /**
     * 数据库操作
     */
    @Autowired
    private XjsTechDao entitymDao;

    @Autowired
    private SYuserDao userDao;

    @Autowired
    private SYDeptDao deptDao;

    /**
     * 审批历史表
     */
    @Autowired
    private PProcessInfoDao pProcessInfoDao;


    @Autowired
    private TSysParamDao tsParamDao;

    @Autowired
    private TSysMessageDao tsMessageDao;

    /**
     * 年审表
     */
    @Autowired
    private XjsYearAuditDao xjsYearAuditDao;

    /**
     * 新项目历史表
     */
    @Autowired
    private XjsTechHisDao xjsTechHisDao;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private TSysLogSvc tSysLogSvc;

    @Autowired
    private SMSSender smsSender;

    public Result doApprove(XjsTechApproveRequest map, RequestPojo requestPojo) {
        Result result = new Result<>();
        // 1.获取当前项目信息,当前节点信息
        XjsTech xjsTech = entitymDao.queryById(map.getId());

        // 2.编辑当前审核人审核状态
        // 所有的流程状态
        TSysParam status = getTSysParam("XJS_CIRCULATION_STATUS");
        List<CirculationStatusBo> circleStatus = null;
        if (status != null) {
            String statusJson = status.getParamValue();
            ObjectMapper mapper = new ObjectMapper();
            try {
                circleStatus = mapper.readValue(statusJson, new TypeReference<List<CirculationStatusBo>>() {
                });
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (CollectionUtils.isEmpty(circleStatus)) {
            result.setResStatus(ResStatus.STATUS_UNAVAILABLE);
            result.setResMsg(ResStatus.STATUS_UNAVAILABLE_MSG);
            return result;
        }
        // 当前节点
        CirculationStatusBo thisStatus = circleStatus.stream().filter(a -> a.getKey().equals(xjsTech.getStatus())).findFirst().orElse(null);
        if (null == thisStatus) {
            result.setResStatus(ResStatus.STATUS_UNAVAILABLE);
            result.setResMsg(ResStatus.STATUS_UNAVAILABLE_MSG);
            return result;
        }

        // 当前用户ID
        String staffId = requestPojo.getSysId();
        // 获取所有审批人，更新当前审批人审批状态
        PProcessInfo processFilter = new PProcessInfo();
        processFilter.setCorrelationId(xjsTech.getId());
        List<PProcessInfo> pProcessInfos = pProcessInfoDao.queryAll(processFilter);
        if (CollectionUtils.isNotEmpty(pProcessInfos)) {
            // 此数据用户信息
            SYuser thisUser = userDao.selectById(xjsTech.getApplyUserId());

            // 是否是当前人审批
            boolean isApproval = false;

            for (PProcessInfo item : pProcessInfos) {
                if (staffId.equals(String.valueOf(item.getProcessUserId())) && xjsTech.getStatus().equals(item.getProcessStatus())) {

                    isApproval = true;

                    item.setStatus(1);
                    item.setRemarks(map.getRemarks());
                    item.setUpdateTime(new Date());
                    item.setTask(map.getTask());
                    item.setAuditStatus(DefaultConstant.NUM_1.equals(map.getAuditStatus()) ? 1 : 2);
                    pProcessInfoDao.updateById(item);

                    // 存历史消息表
                    TSysMessage tsMessage = new TSysMessage();
                    tsMessage.setRelatedId(xjsTech.getId());
                    tsMessage.setRelatedType("审批");
                    tsMessage.setLogTitle("项目技术流程审批");
                    String content = DefaultConstant.NUM_1.equals(item.getAuditStatus()) ? "审批通过" : "审批驳回";
                    tsMessage.setLogContent(xjsTech.getName() + "流程审批" + thisStatus.getName() + content);
                    tsMessage.setCreateBy(String.valueOf(xjsTech.getApplyUserId()));
                    tsMessage.setCreateTime(new Date());
                    tsMessage.setOperateStatus(DefaultConstant.NUM_0);
                    tsMessageDao.insert(tsMessage);

                    // 发短信:  定制化： 流转中的任意一个结点完成审批后是驳回拒绝的结果
                    XjsTechSendSmaRequest sendSms = new XjsTechSendSmaRequest();
                    try {
                        sendSms.setTel(AESTool.decrypt(thisUser.getPhoneNo()));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    if (null != sendSms.getTel()) {
                        sendSms.setCustomerID(thisUser.getUserID());
                        sendSms.setCustomerName(thisUser.getName());
                        sendSms.setCustomerType("1");
                        sendSms.setSrvType("XJS");
                        sendSms.setMessage(SMSSender.getContent(thisUser.getName(), xjsTech.getName(), 1100));
                        smsSender.sendSms(sendSms);
                    }

                    // 驳回，不进行任何操作
                    if (DefaultConstant.NUM_2.equals(item.getAuditStatus())) {
                        // 驳回，不进行任何操作
                        xjsTech.setAuditStatus(DefaultConstant.NUM_4);
                        entitymDao.updateById(xjsTech);
                        result.setResStatus(ResStatus.STATUS_SUCCESS);
                        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
                        return result;
                    }
                }
            }

            if (!isApproval) {
                result.setResStatus(ResStatus.STATUS_EXIST_APPROVAL);
                result.setResMsg(ResStatus.STATUS_APPROVAL_MSG);
                return result;
            }
        } else {
            result.setResStatus(ResStatus.STATUS_EXIST_APPROVAL);
            result.setResMsg(ResStatus.STATUS_APPROVAL_MSG);
            return result;
        }


        //  3.如果当前节点多人审批，需要通过投票的方式，当通过人数大于百分之50时，确定流程是否进行下一步流转
        // 当前流程总人数
        Long total = pProcessInfos.stream().filter(a -> null != a.getProcessStatus() && a.getProcessStatus().equals(xjsTech.getStatus())).count();
        // 通过人数
        Long pass = pProcessInfos.stream().filter(a -> DefaultConstant.NUM_1.equals(a.getAuditStatus())).count();
        if (pass.doubleValue() / total.doubleValue() > DefaultConstant.NUM_05) {
            // 当前节点若还有其他人待审批的改为无需处理
            pProcessInfos.stream().filter(a -> DefaultConstant.NUM_0.equals(a.getStatus()) &&
                    null != a.getProcessStatus() && a.getProcessStatus().equals(xjsTech.getStatus())).forEach(a -> {
                a.setStatus(2);
                a.setUpdateTime(new Date());
                pProcessInfoDao.updateById(a);
            });

            //获取流转人员信息，新增下一次需要审核的人员名单
            TSysParam info = getTSysParam("XJS_FLOW");
            if (info != null) {
                // 数据类型转换
                String infoJson = info.getParamValue();
                ObjectMapper mapper = new ObjectMapper();
                List<ProcessItemBo> processItems = null;
                try {
                    processItems = mapper.readValue(infoJson, new TypeReference<List<ProcessItemBo>>() {
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (null == processItems || null == circleStatus) {
                    result.setResStatus(ResStatus.STATUS_SUCCESS);
                    result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
                    return result;
                }

                // 没有下个节点了
                if (null == thisStatus.getNextKey()) {
                    // 5.修改当前项目的下一个节点状态为年审
                    xjsTech.setStatus(80);
                    // 已完结状态
                    xjsTech.setAuditStatus(DefaultConstant.NUM_3);
                    entitymDao.updateById(xjsTech);

                    result.setResStatus(ResStatus.STATUS_SUCCESS);
                    result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
                    return result;
                }

                // 4.业务操作：需要进行消息发送、短信发送、操作审批的人员集合
                List<SYuser> syuserList = new ArrayList<>();

                // 获取下一个节点，人员名单
                CirculationStatusBo nextStatus = circleStatus.stream().filter(a -> a.getKey().equals(thisStatus.getNextKey())).findFirst().orElse(null);
                for (ProcessItemBo item : processItems) {
                    // 当前节点信息
                    System.out.println("Process: " + item.getProcess());
                    // 当前节点的下一个节点
                    if (null == item.getProcess() || !item.getProcess().equals(thisStatus.getNextKey())) {
                        continue;
                    }

                    // 当前节点所涉及到的人员ID
                    if (item.getSyuser() != null) {
                        for (ProcessItemBo.SyUserId user : item.getSyuser()) {
                            System.out.println("User ID: " + user.getId());
                            SYuser sYuser = userDao.selectById(user.getId());
                            if (sYuser == null) {
                                continue;
                            }
                            syuserList.add(sYuser);
                        }
                    }
                    // 当前节点所涉及到的部门ID
                    if (CollectionUtils.isNotEmpty(item.getSydept())) {
                        for (ProcessItemBo.SyDeptId dept : item.getSydept()) {
                            System.out.println("Manager: " + dept.getManager());
                            Page page = new Page();
                            HashMap userFilter = new HashMap<>();
                            userFilter.put("DepID", dept.getManager());
                            List<SYuser> syuser = userDao.selectList(page, userFilter);
                            syuserList.addAll(syuser);
                        }
                    }

                    // 当前节点所涉及到的组ID
                    if (CollectionUtils.isNotEmpty(item.getSygrouph())) {
                        for (ProcessItemBo.SyGroupId group : item.getSygrouph()) {
                            System.out.println("Group ID: " + group.getId());
                            Page page = new Page();
                            HashMap userFilter = new HashMap<>();
                            userFilter.put("UserGroupID", group.getId());
                            List<SYuser> syuser = userDao.selectList(page, userFilter);
                            syuserList.addAll(syuser);
                        }
                    }
                }

                // 进行业务操作，消息发送、短信发送、提交流程审批
                for (SYuser sYuser : syuserList) {
                    // 提交流程
                    PProcessInfo pProcessInfo = new PProcessInfo();
                    pProcessInfo.setCorrelationId(xjsTech.getId());
                    pProcessInfo.setCreateTime(new Date());
                    pProcessInfo.setTaskName(nextStatus.getName() + "审核");
                    pProcessInfo.setCategory(1);
                    pProcessInfo.setProcessStatus(nextStatus.getKey());
                    pProcessInfo.setProcessBy(sYuser.getName());
                    pProcessInfo.setProcessUserId(Long.valueOf(sYuser.getId()));
                    pProcessInfo.setProcessOper(nextStatus.getName() + "审核");
                    pProcessInfo.setStatus(0);
                    pProcessInfoDao.insert(pProcessInfo);

                    // 发送短信：给相应的下一阶段审核人
                    XjsTechSendSmaRequest sendSms = new XjsTechSendSmaRequest();
                    try {
                        sendSms.setTel(AESTool.decrypt(sYuser.getPhoneNo()));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    if (null != sendSms.getTel()) {
                        sendSms.setCustomerID(sYuser.getEmpNo());
                        sendSms.setCustomerName(sYuser.getName());
                        sendSms.setCustomerType("1");
                        sendSms.setSrvType("XJS");
                        sendSms.setMessage(SMSSender.getContent(sYuser.getName(), xjsTech.getName(), nextStatus.getKey()));
                        smsSender.sendSms(sendSms);
                    }

                    // 存历史消息表
                    TSysMessage tsMessage = new TSysMessage();
                    tsMessage.setRelatedId(xjsTech.getId());
                    tsMessage.setRelatedType("审批");
                    tsMessage.setLogTitle("项目技术流程审批");
                    tsMessage.setLogContent("您有一条" + xjsTech.getName() + "新技术新项目待审批");
                    tsMessage.setCreateBy(String.valueOf(sYuser.getId()));
                    tsMessage.setCreateTime(new Date());
                    tsMessage.setOperateStatus(DefaultConstant.NUM_0);
                    tsMessageDao.insert(tsMessage);
                }

                // 需要填上开通时间
                if (null != map.getOpenTime()) {
                    xjsTech.setOpenTime(map.getOpenTime());
                    xjsTech.setYearAuditNum(1);
                }

                // 5.修改当前项目的下一个节点状态
                xjsTech.setStatus(nextStatus.getKey());
                entitymDao.updateById(xjsTech);

                // 6. 财务核价 -》医务处开通，这个是自动化流程，自动走流程
                if (null != map.getOpenTime() && DefaultConstant.NUM_70.equals(nextStatus.getKey()) && CollectionUtils.isNotEmpty(syuserList)) {
                    RequestPojo pojo = new RequestPojo();
                    pojo.setSysId(String.valueOf(syuserList.get(0).getId()));
                    map.setAuditStatus(1);
                    map.setRemarks("系统自动通过");
                    map.setOpenTime(null);
                    map.setId(xjsTech.getId());
                    this.doApprove(map, pojo);
                }

                String content = DefaultConstant.NUM_1.equals(map.getAuditStatus()) ? "审批通过" : "审批驳回";

                tSysLogSvc.saveLogInfo(Long.valueOf(xjsTech.getId()), "xjsproject", "审批项目", "项目名称:" + xjsTech.getName(), content, "成功", requestPojo);
            }
        }

        result.setResStatus(ResStatus.STATUS_SUCCESS);
        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
        return result;
    }

    /**
     * 获取系统参数
     *
     * @param paramName
     * @return
     */
    private TSysParam getTSysParam(String paramName) {
        TSysParam tsParam = new TSysParam();
        tsParam.setParamName(paramName);
        TSysParam info = tsParamDao.selectOne(tsParam);
        return info;
    }
}
